#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#pragma warning(push)
 #pragma warning(disable : 6386)
  #include <atlpath.h>
 #pragma warning(default : 6386)
#pragma warning(pop)

#include "..\tdd.h"

class TestRunner
{
	TDD::Discriminator& m_discriminator;
	TDD::Reporter& m_reporter;
public:
	TestRunner(TDD::Discriminator& discriminator, TDD::Reporter& reporter)
		: m_discriminator(discriminator)
		, m_reporter(reporter)
	{}
	virtual ~TestRunner() {}

	bool RunTests(const CPath& testDll)
	{
		::SetErrorMode(SEM_FAILCRITICALERRORS);   // tell the OS to not pop-up message boxes for anything other than critical errors

		class ResetCurrentDirectory
		{
			CString m_orig;
		public:
			ResetCurrentDirectory(const CString& testDll)
			{
				::GetCurrentDirectory(MAX_PATH, m_orig.GetBuffer(MAX_PATH));
				m_orig.ReleaseBuffer();

				CPath path(testDll);
				path.RemoveFileSpec();
				::SetCurrentDirectory(path);
			}
			~ResetCurrentDirectory()
			{
				::SetCurrentDirectory(m_orig);
			}
		} rcd(testDll);

		bool b = false;
		HINSTANCE hinst = LoadLibrary(testDll);
		if (hinst) {
			void (__stdcall *fnRunTddTests)(TDD::Discriminator&, TDD::Reporter&);
			fnRunTddTests = (void (__stdcall*)(TDD::Discriminator&, TDD::Reporter&))GetProcAddress(hinst, "RunTddTests");
			if (fnRunTddTests) {
				b = true;
				::CoInitialize(NULL); // for test writers' convenience only
				fnRunTddTests(m_discriminator, m_reporter);
				::CoUninitialize();
			}
			::FreeLibrary(hinst);
		}
		return b;
	}
};

#endif
